package com.redteam.models;

import com.redteam.data.beans.Airplane;
import com.redteam.data.beans.CharterCustomer;
import com.redteam.data.beans.CharterPilot;
import com.redteam.data.beans.Instructor;
import com.redteam.data.beans.MaintenanceEngineer;
import com.redteam.data.beans.MaintenanceMemo;
import com.redteam.data.beans.Person;
import com.redteam.data.beans.Pilot;
import com.redteam.data.beans.RentalItem;
import com.redteam.data.beans.Reservation;
import com.redteam.data.beans.Simulator;
import com.redteam.data.beans.Student;
import com.redteam.data.dao.AirplaneDAO;
import com.redteam.data.dao.CharterCustomerDAO;
import com.redteam.data.dao.CharterPilotDAO;
import com.redteam.data.dao.CustomerPilotDAO;
import com.redteam.data.dao.InstructorDAO;
import com.redteam.data.dao.MaintenanceMemoDAO;
import com.redteam.data.dao.MechanicDAO;
import com.redteam.data.dao.PersonsDAO;
import com.redteam.data.dao.PilotDAO;
import com.redteam.data.dao.ReservationDAO;
import com.redteam.data.dao.SimulatorDAO;
import com.redteam.data.dao.StudentDAO;
import com.redteam.data.dao.interfaces.DAO;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * Model class that works with the DAOs
 * @author Franco Morales
 */
public class DAOAccessor {

    /**
     * Default empty constructor
     */
    public DAOAccessor() {
    }
    
    List<Object> objs;
    DAO dao;

    public Person getPersonById(Long id) {
        dao = PersonsDAO.getInstance();
        Person person = null;
        try {
            person = (Person) dao.getSingle(id);
        } catch (SQLException ex) {
            Logger.getLogger(DAOAccessor.class.getName()).log(Level.SEVERE, null, ex);
        }
        return person;
    }

    /**
     * A helper method for getting all the members of a particular type in the database tables
     * @param dao
     * @return A list of objects
     */
    public List<Object> daoGetAll(DAO dao) {
        try {
            objs = dao.getAll();
        } catch (SQLException ex) {
            Logger.getLogger(DAOAccessor.class.getName()).log(Level.SEVERE, null, ex);
        }
        return objs;
    }

    public Airplane getPlane(Map<String, String[]> planeMap) {
        List<Airplane> planes = getAllPlanes();
        Airplane plane = null;
        Long planeId;
        for (Airplane p : planes) {
            planeId = Long.parseLong(planeMap.get("plane")[0]);
            if (p.getId() == planeId) {
                plane = p;
            }
        }
        return plane;
    }

    public Airplane getPlane(long key) throws SQLException {
        dao = AirplaneDAO.getInstance();
        Airplane plane = (Airplane) dao.getSingle(key);
        return plane;
    }

    public Student getStudent(Map<String, String[]> studentMap) {
        List<Student> students = getAllStudents();
        Student student = null;
        Long studentId;
        for (Student p : students) {
            studentId = Long.parseLong(studentMap.get("plane")[0]);
            if (p.getId() == studentId) {
                student = p;
            }
        }
        return student;
    }

    /**
     * Returns a list of Airplanes
     * @return A list of Airplanes
     */
    public List<Airplane> getAllPlanes() {
        List<Airplane> planes = null;

        dao = AirplaneDAO.getInstance();
        objs = daoGetAll(dao);

        planes = (List) objs;
        return planes;
    }

    public List<Person> getAllPersons() {
        List<Person> persons = null;
        dao = PersonsDAO.getInstance();
        objs = daoGetAll(dao);

        persons = (List) objs;
        return persons;
    }

    /**
     *
     * @return
     */
    public List<Reservation> getAllReservations() {
        List<Reservation> reservations = null;
        dao = ReservationDAO.getInstance();
        objs = daoGetAll(dao);
        reservations = (List) objs;
        return reservations;
    }

    /**
     *
     * @return
     */
    public List<Simulator> getAllSimulators() {
        List<Simulator> sims = null;

        dao = SimulatorDAO.getInstance();

        objs = daoGetAll(dao);
        sims = (List) objs;
        return sims;
    }

    public List<Student> getAllStudents() {
        List<Student> students = null;

        dao = StudentDAO.getInstance();

        objs = daoGetAll(dao);
        students = (List) objs;
        return students;
    }

    public List<MaintenanceEngineer> getAllMaintenanceEngineers() {
        List<MaintenanceEngineer> engineers = null;

        dao = MechanicDAO.getInstance();

        objs = daoGetAll(dao);
        engineers = (List) objs;
        return engineers;
    }

    public List<Instructor> getAllInstructors() {
        List<Instructor> instructors = null;

        dao = InstructorDAO.getInstance();

        objs = daoGetAll(dao);
        instructors = (List) objs;
        return instructors;
    }

    public List<CharterCustomer> getAllCharterCustomers() {
        List<CharterCustomer> charterCustomers = null;

        dao = CharterCustomerDAO.getInstance();

        objs = daoGetAll(dao);
        charterCustomers = (List) objs;
        return charterCustomers;
    }

    public List<CharterPilot> getAllCharterPilots() {
        List<CharterPilot> charterPilots = null;

        dao = CharterPilotDAO.getInstance();

        objs = daoGetAll(dao);
        charterPilots = (List) objs;
        return charterPilots;
    }

    /**
     * Returns a list of CharterPilots that can fly a particular Airplane
     * @param parameters
     * @return A list of CharterPilots
     */
    public List<CharterPilot> getCharterPilotsForPlane(Map<String, String[]> parameters) {
        List<CharterPilot> pilots = null;
        List<Airplane> planes = getAllPlanes();

        Airplane plane = null;

        dao = CharterPilotDAO.getInstance();
        objs = daoGetAll(dao);

        Long planeId = Long.parseLong(parameters.get("plane")[0]);
        for (Airplane a : planes) {
            if (a.getId() == planeId) {
                plane = a;
                break;
            }
        }
        pilots = (List) objs;
        List<CharterPilot> relevantPilots = (List) daoGetAll(dao);
        for (CharterPilot p : pilots) {
            for (String e : plane.getEndorsements()) {
                if (!p.getEndorsements().contains(e)) {
                    relevantPilots.remove(p);
                }
            }
        }
        return relevantPilots;
    }

    /**
     * Returns a list of Instructors that can fly a particular Airplane
     * @param parameters
     * @return A list of Instructors
     */
    public List<Instructor> getInstructorsForPlane(Map<String, String[]> parameters) {
        List<Instructor> instructors = null;
        List<Airplane> planes = getAllPlanes();

        Airplane plane = null;

        dao = InstructorDAO.getInstance();
        objs = daoGetAll(dao);

        Long planeId = Long.parseLong(parameters.get("plane")[0]);
        for (Airplane a : planes) {
            if (a.getId() == planeId) {
                plane = a;
                break;
            }
        }
        instructors = (List) objs;
        List<Instructor> relevantInstructors = getAllInstructors();
        for (Instructor i : instructors) {
            for (String e : plane.getEndorsements()) {
                if (!i.getEndorsements().contains(e)) {
                    relevantInstructors.remove(i);
                }
            }
        }
        return relevantInstructors;
    }

    /**
     *
     * @param parameters
     * @return
     */
    public List<Reservation> getCustomerPilotItemSchedules(Reservation res) {
        List<Reservation> allReservations = null;
        List<Reservation> relevantReservations = null;
        Person reserver = null;
        Pilot pilot = null;
        RentalItem item = null;

        allReservations = getAllReservations();

        reserver = res.getReserver();
        pilot = res.getPilot();
        item = res.getRentalItem();
        for (Reservation r : allReservations) {
            if (r.getPilot() == pilot || r.getReserver() == reserver || r.getRentalItem() == item) {
                relevantReservations.add(r);
            }
        }
        return relevantReservations;
    }

    /**
     * @param maintenanceMap
     * @return
     */
    public List<MaintenanceMemo> getMaintenanceMemosForPlane(Map<String, String[]> maintenanceMap) {
        List<MaintenanceMemo> allMemos = null;
        List<MaintenanceMemo> relevantMemos = null;

        Airplane plane = null;

        dao = MaintenanceMemoDAO.getInstance();

        objs = daoGetAll(dao);

        allMemos = (List) objs;
        Long memoId = Long.parseLong(maintenanceMap.get("memo")[0]);
        for (MaintenanceMemo m : allMemos) {
            if (m.getAirplane().getId() == memoId) {
                relevantMemos.add(m);
            }
        }
        return relevantMemos;
    }

    /**
     *
     * @param personMap
     * @return
     */
    public List<Reservation> getReservationsForPerson(Map<String, String[]> personMap) {
        List<Reservation> allReservations = null;
        List<Reservation> relevantReservations = null;

        dao = ReservationDAO.getInstance();

        allReservations = getAllReservations();

        Long personId = Long.parseLong(personMap.get("person")[0]);
        for (Reservation r : allReservations) {
            if (r.getReserver().getId() == personId) {
                relevantReservations.add(r);
            }
        }
        return relevantReservations;
    }

    public int updateReservationState(Map<String, String[]> reservationMap) {
        List<Reservation> reservations = getAllReservations();

        dao = ReservationDAO.getInstance();

        Long resId = Long.parseLong(reservationMap.get("reservation")[0]);
        for (Reservation r : reservations) {
            if (r.getId() == resId) {
                r.setReservationState(reservationMap.get("state")[0]);
                try {
                    dao.update(r);
                } catch (SQLException ex) {
                    Logger.getLogger(DAOAccessor.class.getName()).log(Level.SEVERE, null, ex);
                }
                return 1;
            }
        }
        return 0;
    }

    /**
     *
     * @param reservationMap
     * @return
     */
    public Person getReserverForReservation(Map<String, String[]> reservationMap) {
        List<Reservation> reservations = getAllReservations();
        Person person = null;

        Long resId = Long.parseLong(reservationMap.get("reservation")[0]);
        for (Reservation r : reservations) {
            if (r.getId() == resId) {
                person = r.getReserver();
            }
        }
        return person;
    }

    /**
     *
     * @param reservationMap
     * @return
     */
    public RentalItem getItemForReservation(Map<String, String[]> reservationMap) {
        List<Reservation> reservations = getAllReservations();
        RentalItem item = null;

        Long resId = Long.parseLong(reservationMap.get("reservation")[0]);
        for (Reservation r : reservations) {
            if (r.getId() == resId) {
                item = r.getRentalItem();
            }
        }
        return item;
    }

    /**
     *
     * @param reservationMap
     * @return
     */
    public Pilot getPilotForReservation(Map<String, String[]> reservationMap) {
        List<Reservation> reservations = getAllReservations();
        Pilot pilot = null;

        Long resId = Long.parseLong(reservationMap.get("reservation")[0]);
        for (Reservation r : reservations) {
            if (r.getId() == resId) {
                pilot = r.getPilot();
            }
        }
        return pilot;
    }

    /**
     *
     * @param reservationMap
     * @param state
     * @return
     */
    public int updateReservation(Map<String, String[]> reservationMap) {
        List<Reservation> reservations = getAllReservations();

        Long resId = Long.parseLong(reservationMap.get("reservation")[0]);
        for (Reservation r : reservations) {
            if (r.getId() == resId) {
                r.setReservationState(reservationMap.get("state")[0]);
                return 1;
            }
        }
        return 0;
    }

    /**
     *
     * @param engineerMap
     * @return
     */
    public List<MaintenanceMemo> getMaintenanceMemoForEngineer(Map<String, String[]> engineerMap) {
        List<MaintenanceMemo> allMemos = null;
        List<MaintenanceMemo> relevantMemos = null;

        dao = MechanicDAO.getInstance();

        objs = daoGetAll(dao);
        allMemos = (List) objs;
        Long maintEngId = Long.parseLong(engineerMap.get("engineer")[0]);
        for (MaintenanceMemo m : allMemos) {
            if (m.getMechanic().getId() == maintEngId) {
                relevantMemos.add(m);
            }
        }
        return relevantMemos;
    }

    /**
     *
     * @param engineerMap
     * @return
     */
    public List<MaintenanceMemo> getMaintenanceMemoForEngineer(long engineerId) {
        List<MaintenanceMemo> allMemos = new ArrayList<MaintenanceMemo>();

        MaintenanceMemoDAO mmdao = MaintenanceMemoDAO.getInstance();
        try {
            allMemos = (List) mmdao.getAllforMechanic(engineerId);
        } catch (SQLException ex) {
            Logger.getLogger(DAOAccessor.class.getName()).log(Level.SEVERE, null, ex);
        }
        for (MaintenanceMemo mm : allMemos) {
            System.out.println(mm.getID() + " " + mm.getStatus() + " " + mm.getNotes());
        }
        return allMemos;
    }

    public int submitReservation(Map<String, Reservation> reservationMap) {
        dao = ReservationDAO.getInstance();
        Reservation reservation = reservationMap.get("reservation");
        try {
            return dao.insert(reservation);
        } catch (SQLException ex) {
            Logger.getLogger(DAOAccessor.class.getName()).log(Level.SEVERE, null, ex);
        }
        return 0;
    }

    public int revokeStudentEndorsement(Map<String, String[]> studentMap) {
        List<Student> students = getAllStudents();
        List<String> endorsements = null;
        dao = StudentDAO.getInstance();
        Student student = null;

        Long studentId = Long.parseLong(studentMap.get("student")[0]);
        for (Student s : students) {
            if (s.getId() == studentId) {
                student = s;
            }
        }
        endorsements = student.getEndorsements();
        endorsements.remove(studentMap.get("endorsement")[0]);
        student.setEndorsements(endorsements);
        try {
            dao.insert(student);
            return 1;
        } catch (SQLException ex) {
            Logger.getLogger(DAOAccessor.class.getName()).log(Level.SEVERE, null, ex);
        }
        return 0;
    }

    public int addStudentEndorsement(Map<String, String[]> studentMap) {
        List<Student> students = null;
        List<String> endorsements = null;
        dao = StudentDAO.getInstance();
        objs = daoGetAll(dao);
        Student student = null;

        students = (List) objs;
        Long studentId = Long.parseLong(studentMap.get("student")[0]);
        for (Student s : students) {
            if (s.getId() == studentId) {
                student = s;
            }
        }
        endorsements = student.getEndorsements();
        endorsements.add(studentMap.get("endorsement")[0]);
        student.setEndorsements(endorsements);
        try {
            dao.insert(student);
            return 1;
        } catch (SQLException ex) {
            Logger.getLogger(DAOAccessor.class.getName()).log(Level.SEVERE, null, ex);
        }
        return 0;
    }

    public List<Reservation> getAllforAnyItem(long rentalItemId) {
        List<Reservation> reservationList = new ArrayList<Reservation>();

        try {
            reservationList = ReservationDAO.getInstance().getAllforAnyItem(rentalItemId);
        } catch (SQLException ex) {
        }
        return reservationList;

    }

    /**
     * Returns an array list of all the reservation for given renter Id
     * @param renterId
     * @return reservationListPerPerson
     */
    public List<Reservation> getReservationListPerPersonID(long renterId) {
        List<Reservation> reservationListPerPerson = new ArrayList<Reservation>();
         List<Reservation> allReservations = new ArrayList<Reservation>();
        allReservations.addAll(getAllReservations());
        for (Reservation res : allReservations) {
            if (res.getId() == renterId) {
                reservationListPerPerson.add(res);
            }
        }
        return reservationListPerPerson;
    }

    public List<Pilot> getAllPilots() {
        List<Pilot> pilots = null;
        List<Person> persons = null;
        dao = PilotDAO.getInstance();
        Pilot pilot = null;
        Student student = null;
        Instructor instructor = null;
        CharterPilot cPilot = null;

        objs = daoGetAll(dao);
        persons = (List) objs;
        try {
            for (Person p : persons) {
                if (p.getDiscriminator().equals("pilot")) {
                    pilots.add(pilot.getClass().cast(p.getClass().newInstance()));
                } else if (p.getDiscriminator().equals("stud")) {
                    pilots.add(student.getClass().cast(p.getClass().newInstance()));
                } else if (p.getDiscriminator().equals("instr")) {
                    pilots.add(instructor.getClass().cast(p.getClass().newInstance()));
                } else if (p.getDiscriminator().equals("ch")) {
                    pilots.add(cPilot.getClass().cast(p.getClass().newInstance()));
                }
            }
        } catch (InstantiationException ex) {
            Logger.getLogger(DAOAccessor.class.getName()).log(Level.SEVERE, null, ex);
        } catch (IllegalAccessException ex) {
            Logger.getLogger(DAOAccessor.class.getName()).log(Level.SEVERE, null, ex);
        }
        return pilots;
    }

    public List<Airplane> getPlanesForPilot(Pilot pilot) {
        List<Airplane> planes = getAllPlanes();
        List<Airplane> relevantPlanes = getAllPlanes();
        for (Airplane a : planes) {
            for (String s : a.getEndorsements()) {
                if (!pilot.getEndorsements().contains(s)) {
                    relevantPlanes.remove(a);
                }
            }
        }
        return relevantPlanes;
    }

    /**
     *
     * @param userName
     * @return
     */
    public Person getPersonByUsername(String userName) {
        Person person = null;
        List<Person> people = getAllPersons();
        for (Person p : people) {
            if (p.getUsername().equals(userName)) {
                person = p;
            }
        }
        return person;
    }

    public Student getStudentByID(long id) {
        Student student = null;
        List<Student> students = getAllStudents();
        for (Student stud : students) {
            if (stud.getId() == id) {
                student = stud;
            }
        }
        return student;
    }
    /*
     * does not work
     */

    public MaintenanceEngineer getMaintenanceEngineerByID(long id) {
        MaintenanceEngineer mainteng = null;
        List<MaintenanceEngineer> engineers = getAllMaintenanceEngineers();
        for (MaintenanceEngineer me : engineers) {
            if (me.getId() == id) {
                mainteng = me;
            }
        }
        return mainteng;
    }

    public Instructor getInstructorByID(long id) {
        Instructor instructor = null;
        List<Instructor> instructors = getAllInstructors();
        for (Instructor instr : instructors) {
            if (instr.getId() == id) {
                instructor = instr;
            }
        }
        return instructor;
    }

    public CharterCustomer getCharterCustomerByID(long id) {
        CharterCustomer charterCustomer = null;
        List<CharterCustomer> charterCustomers = getAllCharterCustomers();
        for (CharterCustomer chrtcus : charterCustomers) {
            if (chrtcus.getId() == id) {
                charterCustomer = chrtcus;
            }
        }
        return charterCustomer;
    }

    public CharterPilot getCharterPilotByID(long id) {
        CharterPilot charterPilot = null;
        List<CharterPilot> charterPilots = getAllCharterPilots();
        for (CharterPilot chrtplt : charterPilots) {
            if (chrtplt.getId() == id) {
                charterPilot = chrtplt;
            }
        }
        return charterPilot;
    }

    public Pilot getPilotByID(long id) {
        Pilot pilot = null;
        List<Pilot> pilots = new ArrayList<Pilot>();
        pilots.addAll(getAllCustomerPilots());
        for (Pilot plt : pilots) {
            if (plt.getId() == id) {
                pilot = plt;
            }
        }
        return pilot;
    }

    public List<Pilot> getAllCustomerPilots(){
        List<Pilot> pilots = new ArrayList<Pilot>();
        DAO dao = CustomerPilotDAO.getInstance();
        pilots=(List)daoGetAll(dao);

        return pilots;
    }

    public Reservation getReservationById(Long id) {
        Reservation reservation = null;
        List<Reservation> allReservations = new ArrayList<Reservation>();
        allReservations.addAll(getAllReservations());
        for (Reservation res : allReservations) {
            if (res.getId() == id) {
                reservation = res;
            }
        }
        return reservation;
    }

    public Simulator getSimulator(long key) throws SQLException {
        Simulator sim = (Simulator) dao.getSingle(key);
        return sim;
    }

    public List<Reservation> getAllAcceptedReservationsById(long id) {
        List<Reservation> reservations = new ArrayList<Reservation>();
        List<Reservation> allReservations = new ArrayList<Reservation>();
        allReservations.addAll(getAllReservations());
        for (Reservation res : allReservations) {
            if (res.getReserver().getId() == id && (res.getReservationState().equals("accepted") || res.getReservationState().equals("inProgress"))) {
                reservations.add(res);
            }
        }
        return reservations;
    }
}
